package zisu.netty.practice.NIO;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * @Desc: "多个buffer 的 分散操作  和 聚集操作"
 * @Author: caixiang
 * @DATE: 2020/7/1 14:16
 *
 * Scattering: 将数据写入到buffer时，可以采用buffer数组，依次写入
 * Gathering: 从buffer读取数据时候，也可以采用buffer数组 ，依次读
 */
public class ScatteringAndGathering {

    public static void main(String[] args) throws IOException {

        // 使用ServerSocketChannel 和 SocketChannel 网络
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        InetSocketAddress inetSocketAddress = new InetSocketAddress(7000);

        //绑定端口到socket，，并启动
        serverSocketChannel.socket().bind(inetSocketAddress);

        //创建一个buffer数组（服务器端）
        ByteBuffer[] byteBuffers = new ByteBuffer[2];
        byteBuffers[0] = ByteBuffer.allocate(5);
        byteBuffers[1] = ByteBuffer.allocate(3);

        // 等待客户端连接
        // 当有连接进来的时候,,这里的channel就是client 连接上来的通道，，这样client 和 server 就通过这个channel关联起来了。
        // 当有连接进来的时候 serverSocketChannel会自动分配一个socketChannel 给这个client。
        SocketChannel socketChannel = serverSocketChannel.accept();

        //假定从客户端接收8个字节
        int messageLength = 8;

        //拿到channel 后 循环读取
        while(true){
            int byteRead = 0;
            while (byteRead<messageLength){
                long l = socketChannel.read(byteBuffers);
                byteRead += l; //累计读取字节数
                System.out.println("byteRead="+byteRead);
                //使用流打印，看看当前的这个buffer的position 和 limit
                System.out.println();
                Arrays.asList(byteBuffers).stream().map(buffer -> "position="+buffer.position()+",limit="+buffer.limit()).forEach(System.out::println);
            }
            //将所有的buffers 进行翻转
            Arrays.asList(byteBuffers).forEach(buffer->buffer.flip());

            //将数据显示到客户端。
            long byteWrite = 0;
            while (byteWrite<messageLength){
                //把读过来的消息 回送给客户端。
                long l = socketChannel.write(byteBuffers);
                byteWrite += l;
            }

            //将所有的buffer 复位

            Arrays.asList(byteBuffers).forEach(byteBuffer -> byteBuffer.clear());

            System.out.println("byteRead: "+byteRead+ ",byteWrite = "+byteWrite+ ",messageLength = "+messageLength);
        }

    }
}
